using System;
using System.Collections.Generic;
using System.Text;
using DTO;
using DAO;
using System.Data;
using System.Globalization;

namespace BUS
{
    /// <summary> 
    ///Author: daiduong19051986@gmail.com 
    /// <summary>
    public class RuleProfileControl
    {
        private string business;
        private string cachedTable;
        DataTable _dtMaster;
        DataTable _dtDetail;
        DataTable _dtResult;
        private RuleProfileDataAccess _objDAO;
        #region Local Variable

        #endregion Local Variable

        #region Method

        public RuleProfileControl(String bus)
        {
            business = bus;
            _objDAO = new RuleProfileDataAccess();
        }
        public RuleProfileInfo Get(string db, String RULESET_CODE, ref string sErr)
        {
            return _objDAO.Get(db, RULESET_CODE, ref sErr);
        }

        public DataTable GetAll(string db, ref string sErr)
        {
            return _objDAO.GetAll(db, ref sErr);
        }

        public Int32 Add(string db, RuleProfileInfo obj, ref string sErr)
        {
            return _objDAO.Add(db, obj, ref sErr);
        }

        public string Update(string db, RuleProfileInfo obj)
        {
            return _objDAO.Update(db, obj);
        }

        public string Delete(string db, String RULESET_CODE)
        {
            return _objDAO.Delete(db, RULESET_CODE);

        }
        public Boolean IsExist(string db, String RULESET_CODE)
        {
            return _objDAO.IsExist(db, RULESET_CODE);
        }


        public string InsertUpdate(string db, RuleProfileInfo obj)
        {
            string sErr = "";
            if (IsExist(db, obj.RULESET_CODE))
            {
                sErr = _objDAO.Update(db, obj);
            }
            else _objDAO.Add(db, obj, ref sErr);
            return sErr;
        }

        public DataTable GetTransferOut(string dtb, object from, object to, ref string sErr)
        {
            return _objDAO.GetTransferOut(dtb, from, to, ref sErr);
        }

        public DataTable ToTransferInStruct()
        {
            return RuleProfileInfo.ToDataTable();
        }

        public string TransferIn(string db, DataRow row)
        {
            RuleProfileInfo inf = new RuleProfileInfo(row);
            return InsertUpdate(db, inf);
        }
        #endregion Method

        public object BeginTransaction(ref string sErr)
        {
            return _objDAO.BeginTransaction(ref sErr);

        }
        public bool CommitTransaction(ref string sErr)
        {
            return _objDAO.CommitTransaction(ref sErr);

        }
        public bool RollbackTransaction(ref string sErr)
        {
            return _objDAO.RollbackTransaction(ref sErr);

        }
        public void SetTransaction(object o)
        {
            _objDAO.SetTransaction(o);
        }

        public DataTable GetMaster(string db, string aTable, ref string sErr)
        {
            if (cachedTable == null || cachedTable != aTable)
            {
                DataTable dtMaster = null;
                DataTable dtDetail = null;
                DataTable dtResult = null;
                dtMaster = _objDAO.GetAllby(db, aTable, ref  sErr);
                if (sErr == "") dtResult = _objDAO.GetResult(db, aTable, ref  sErr);

                if (sErr == "")
                {
                    _dtMaster = dtMaster;
                    _dtDetail = dtDetail;
                    _dtResult = dtResult;
                    cachedTable = aTable;
                }
            }
            return _dtMaster;
        }

        /// <summary>
        /// Validate the record
        /// </summary>
        /// <param name="aTable">Table Name</param>
        /// <param name="dttemp">The records is valied</param>
        /// <param name="sErr">Returned Message</param>
        /// <returns> 1: Error</returns>
        public int Valid_Rule(string db, string aTable, DataTable dttemp, ref string sErr)
        {
            //string strErr = "";
            int result = 0;

            GetMaster(db, aTable, ref sErr);

            if (sErr == "" && _dtMaster != null && _dtMaster.Rows.Count > 0)
            {
                result = ValidFromResult(dttemp, ref sErr);
                //foreach (DataRow rMaster in _dtMaster.Rows)
                //{
                //    int isErr1 = 0;
                //    if (_dtResult != null && _dtResult.Rows.Count > 0)
                //    {
                //        isErr1 += ValidFromResult(rMaster["RULESET_CODE"].ToString(), dttemp, ref sErr);
                //    }
                //    //else
                //    //{
                //    //    isErr1 += ValidFromDetail(rMaster["RULESET_CODE"].ToString(), dttemp, ref strErr);
                //    //}
                //}

            }


            //sErr = strErr;
            return result;
        }

        private int ValidFromResult(DataTable dttemp, ref string sErr)
        {
            int isErr1 = 0;

            foreach (DataRow rRuleSet in _dtResult.Rows)
            {
                if (ValidRule(dttemp, ref sErr, rRuleSet) == 1)
                    isErr1 = 1;

            }

            return isErr1;
        }

        private int ValidRule(DataTable dttemp, ref string sErr, DataRow rRuleSet)
        {
            int isErr1 = 0;
            string errStr1 = rRuleSet["MESSAGE"].ToString();
            string strquery = rRuleSet["WHERE_CLAUSE"].ToString();


            string aItem = "";
            // de lam sau
            DataRow[] arrdr = dttemp.Select(strquery);
            if (arrdr.Length > 0)
            {
                if (rRuleSet["IS_ERROR"].ToString() == "Y") isErr1 = 1;

                for (int n = 0; n < arrdr.Length; n++)
                {
                    aItem = aItem + " " + arrdr[n]["ItemCode"].ToString();
                }

                if (aItem.Length > 2) sErr += string.Format("\n {0} : {1}", aItem, errStr1);
                else sErr += errStr1;
            }
            return isErr1;
        }

        public string updateRuleResult(string db, DTO.RuleProfileInfo inf, DataTable dtDetail = null)
        {
            string sErr = "";

            DataTable dtResult = new DataTable();
            if (sErr == "")
                dtResult = GenResult(db, inf, dtDetail, ref sErr);
            if (sErr == "")
            {
                sErr = delResult(db, inf.RULESET_CODE);
            }
            if (sErr == "")
            {
                foreach (DataRow r in dtResult.Rows)
                {
                    if (sErr != "") break;
                    addResult(db, r, ref sErr);
                }
            }

            return sErr;
        }

        public string delResult(string db, string RULESET_CODE)
        {
            return _objDAO.delResult(db, RULESET_CODE);
        }


        private void addResult(string db, DataRow r, ref string sErr)
        {
            _objDAO.addResult(db, r, ref sErr);
        }

        private DataTable GenResult(string db, DTO.RuleProfileInfo inf, DataTable dtDetail, ref string sErr)
        {
            DataTable dtResult = new DataTable();
            if (dtDetail == null)
            {
                dtDetail = _objDAO.GetDetail(db, inf.RULESET_CODE, ref sErr);
            }

            int isErr1 = 0;
            int index = 0;
            dtResult.Columns.AddRange(new DataColumn[] { new DataColumn("RESULT_ID"), new DataColumn("RULESET_CODE"), new DataColumn("MESSAGE"), new DataColumn("IS_ERROR"), new DataColumn("WHERE_CLAUSE") });
            for (int j = 0; j < 10; j++)
            {
                string errStr1 = "";
                string aField = "";
                string strquery = "";
                string aCol = "COL" + j;
                string strWhere = " ( COL" + j + " = 'Y' OR  COL" + j + " = 'N' OR  COL" + j + " = 'X' )";
                DataRow[] arrRuleSet = dtDetail.Select(string.Format("RULESET_CODE = '{0}' AND {1}", inf.RULESET_CODE, strWhere));// .GetbyRuleSetCode(.ToString(), strWhere, ref sErr);
                if (arrRuleSet.Length > 0)
                {
                    foreach (DataRow rDetail in arrRuleSet)
                    {
                        if (rDetail[aCol].ToString().ToUpper() == "Y")
                        {
                            if (rDetail["COMMAND"].ToString().ToUpper() == "IF")
                            {
                                strquery = strquery + ") AND (";
                            }
                            else
                            {
                                strquery = strquery + "   OR  ";
                            }
                            if (rDetail["START"].ToString() != "0" && rDetail["START"].ToString() != "")
                            {
                                aField = " SUBSTRING(" + rDetail["FIELD"].ToString() + ", " + rDetail["START"].ToString() + (rDetail["LENGTH"] == null ? "0" : ", " + rDetail["LENGTH"].ToString()) + ")";
                            }
                            else
                            {
                                aField = rDetail["FIELD"].ToString();
                            }
                            switch (rDetail["OPERATOR"].ToString())
                            {
                                case "SPACE":
                                    strquery = strquery + "(" + aField + " is null OR TRIM(" + rDetail["FIELD"].ToString() + ")='') ";
                                    break;
                                case "EXISTS":
                                    strquery = strquery + "(" + aField + " is not null AND TRIM(" + rDetail["FIELD"].ToString() + ")<>'') ";
                                    break;
                                default:
                                    switch (rDetail["FIELD"].ToString())
                                    {
                                        case "Amount":
                                        case "Quantity":
                                        case "Period":
                                        case "Average":
                                        case "MINSTOCK":
                                        case "MAXSTOCK":
                                            //Nummeric field
                                            strquery = strquery + aField + " " + rDetail["OPERATOR"].ToString() + rDetail["VALUE"].ToString() + " ";
                                            break;
                                        case "TransDate":
                                        case "ShipmentDate":
                                            // Date field
                                            DateTime aFieldtime = DateTime.ParseExact(aField, "ddMMyyyy", CultureInfo.InvariantCulture);
                                            DateTime avaluetime = DateTime.ParseExact(rDetail["VALUE"].ToString(), "ddMMyyyy", CultureInfo.InvariantCulture);
                                            strquery = strquery + aFieldtime.ToString("yyyyMMdd") + " " + rDetail["OPERATOR"].ToString() + " '" + avaluetime.ToString("yyyyMMdd") + "' ";
                                            break;
                                        default:
                                            // String field
                                            strquery = strquery + aField + " " + rDetail["OPERATOR"].ToString() + " '" + rDetail["VALUE"].ToString() + "' ";
                                            break;
                                    }
                                    break;
                            }
                        }
                        else if (rDetail[aCol].ToString().ToUpper() == "N")
                        {

                            if (rDetail["COMMAND"].ToString().ToUpper() == "IF")
                            {
                                strquery = strquery + ") AND (";
                            }
                            else
                            {
                                strquery = strquery + "  AND  ";
                            }
                            if (rDetail["START"].ToString() != "0" && rDetail["START"].ToString() != "")
                            {

                                aField = " SUBSTRING(" + rDetail["FIELD"].ToString() + ", " + rDetail["START"].ToString() + (rDetail["LENGTH"] == null ? "0" : ", " + rDetail["LENGTH"].ToString()) + ")";
                            }
                            else
                            {
                                aField = rDetail["FIELD"].ToString();
                            }
                            switch (rDetail["OPERATOR"].ToString())
                            {
                                case "SPACE":
                                    strquery = strquery + " NOT (" + aField + " is null OR TRIM(" + rDetail["FIELD"].ToString() + ")='') ";
                                    break;
                                case "EXISTS":
                                    strquery = strquery + " NOT (" + aField + " is not null AND TRIM(" + rDetail["FIELD"].ToString() + ")<>'') ";
                                    break;
                                default:
                                    switch (rDetail["FIELD"].ToString())
                                    {
                                        case "Amount":
                                        case "Quantity":
                                        case "Period":
                                        case "Average":
                                        case "MINSTOCK":
                                        case "MAXSTOCK":
                                            //Nummeric field
                                            strquery = strquery + " NOT (" + aField + " " + rDetail["OPERATOR"].ToString() + rDetail["VALUE"].ToString() + ") ";
                                            break;
                                        case "TransDate":
                                        case "ShipmentDate":
                                            // Date field
                                            DateTime aFieldtime = DateTime.ParseExact(aField, "ddMMyyyy", CultureInfo.InvariantCulture);
                                            DateTime avaluetime = DateTime.ParseExact(rDetail["VALUE"].ToString(), "ddMMyyyy", CultureInfo.InvariantCulture);
                                            strquery = strquery + " NOT (" + aFieldtime.ToString("yyyyMMdd") + " " + rDetail["OPERATOR"].ToString() + " '" + avaluetime.ToString("yyyyMMdd") + "') ";
                                            break;
                                        default:
                                            // String field
                                            strquery = strquery + " NOT (" + aField + " " + rDetail["OPERATOR"].ToString() + " '" + rDetail["VALUE"].ToString() + "') ";
                                            break;
                                    }
                                    break;
                            }
                        }
                        else if (rDetail[aCol].ToString().ToUpper() == "X")
                        {
                            errStr1 = errStr1 + rDetail["VALUE"].ToString() + ".";
                            if (rDetail["COMMAND"].ToString().ToUpper() == "ERROR")
                                isErr1 = 1;
                            // break;
                        }
                    }

                    if (strquery != "")
                    {
                        strquery = "  (" + strquery.Substring(7, strquery.Length - 7) + ")";
                    }
                    string aItem = "";

                    dtResult.Rows.Add(string.Format("{0:00}", index++), inf.RULESET_CODE, errStr1, isErr1 == 1 ? "Y" : "N", strquery);

                }
            }
            return dtResult;
        }

        private int ValidFromDetail(string ruleSetCode, DataTable dttemp, ref string strErr)
        {
            int result = 0;
            bool X = false;
            int isErr1 = 0;
            for (int j = 0; j < 10; j++)
            {
                string errStr1 = "";
                string aField = "";
                string strquery = "";
                string aCol = "COL" + j;
                string strWhere = " ( COL" + j + " = 'Y' OR  COL" + j + " = 'N' OR  COL" + j + " = 'X' )";
                DataRow[] arrRuleSet = _dtDetail.Select(string.Format("RULESET_CODE = '{0}' AND {1}", ruleSetCode, strWhere));// .GetbyRuleSetCode(.ToString(), strWhere, ref sErr);
                if (arrRuleSet.Length > 0)
                {
                    foreach (DataRow rDetail in arrRuleSet)
                    {
                        if (rDetail[aCol].ToString().ToUpper() == "Y")
                        {
                            if (rDetail["COMMAND"].ToString().ToUpper() == "IF")
                            {
                                strquery = strquery + ") AND (";
                            }
                            else
                            {
                                strquery = strquery + "   OR  ";
                            }
                            if (rDetail["START"].ToString() != "0" && rDetail["START"].ToString() != "")
                            {
                                aField = " SUBSTRING(" + rDetail["FIELD"].ToString() + ", " + rDetail["START"].ToString() + (rDetail["LENGTH"] == null ? "0" : ", " + rDetail["LENGTH"].ToString()) + ")";
                            }
                            else
                            {
                                aField = rDetail["FIELD"].ToString();
                            }
                            switch (rDetail["OPERATOR"].ToString())
                            {
                                case "SPACE":
                                    strquery = strquery + "(" + aField + " is null OR TRIM(" + rDetail["FIELD"].ToString() + ")='') ";
                                    break;
                                case "EXISTS":
                                    strquery = strquery + "(" + aField + " is not null AND TRIM(" + rDetail["FIELD"].ToString() + ")<>'') ";
                                    break;
                                default:
                                    switch (rDetail["FIELD"].ToString())
                                    {
                                        case "Amount":
                                        case "Quantity":
                                        case "Period":
                                        case "Average":
                                        case "MINSTOCK":
                                        case "MAXSTOCK":
                                            //Nummeric field
                                            strquery = strquery + aField + " " + rDetail["OPERATOR"].ToString() + rDetail["VALUE"].ToString() + " ";
                                            break;
                                        case "TransDate":
                                        case "ShipmentDate":
                                            // Date field
                                            DateTime aFieldtime = DateTime.ParseExact(aField, "ddMMyyyy", CultureInfo.InvariantCulture);
                                            DateTime avaluetime = DateTime.ParseExact(rDetail["VALUE"].ToString(), "ddMMyyyy", CultureInfo.InvariantCulture);
                                            strquery = strquery + aFieldtime.ToString("yyyyMMdd") + " " + rDetail["OPERATOR"].ToString() + " '" + avaluetime.ToString("yyyyMMdd") + "' ";
                                            break;
                                        default:
                                            // String field
                                            strquery = strquery + aField + " " + rDetail["OPERATOR"].ToString() + " '" + rDetail["VALUE"].ToString() + "' ";
                                            break;
                                    }
                                    break;
                            }
                        }
                        else if (rDetail[aCol].ToString().ToUpper() == "N")
                        {

                            if (rDetail["COMMAND"].ToString().ToUpper() == "IF")
                            {
                                strquery = strquery + ") AND (";
                            }
                            else
                            {
                                strquery = strquery + "  AND  ";
                            }
                            if (rDetail["START"].ToString() != "0" && rDetail["START"].ToString() != "")
                            {

                                aField = " SUBSTRING(" + rDetail["FIELD"].ToString() + ", " + rDetail["START"].ToString() + (rDetail["LENGTH"] == null ? "0" : ", " + rDetail["LENGTH"].ToString()) + ")";
                            }
                            else
                            {
                                aField = rDetail["FIELD"].ToString();
                            }
                            switch (rDetail["OPERATOR"].ToString())
                            {
                                case "SPACE":
                                    strquery = strquery + " NOT (" + aField + " is null OR TRIM(" + rDetail["FIELD"].ToString() + ")='') ";
                                    break;
                                case "EXISTS":
                                    strquery = strquery + " NOT (" + aField + " is not null AND TRIM(" + rDetail["FIELD"].ToString() + ")<>'') ";
                                    break;
                                default:
                                    switch (rDetail["FIELD"].ToString())
                                    {
                                        case "Amount":
                                        case "Quantity":
                                        case "Period":
                                        case "Average":
                                        case "MINSTOCK":
                                        case "MAXSTOCK":
                                            //Nummeric field
                                            strquery = strquery + " NOT (" + aField + " " + rDetail["OPERATOR"].ToString() + rDetail["VALUE"].ToString() + ") ";
                                            break;
                                        case "TransDate":
                                        case "ShipmentDate":
                                            // Date field
                                            DateTime aFieldtime = DateTime.ParseExact(aField, "ddMMyyyy", CultureInfo.InvariantCulture);
                                            DateTime avaluetime = DateTime.ParseExact(rDetail["VALUE"].ToString(), "ddMMyyyy", CultureInfo.InvariantCulture);
                                            strquery = strquery + " NOT (" + aFieldtime.ToString("yyyyMMdd") + " " + rDetail["OPERATOR"].ToString() + " '" + avaluetime.ToString("yyyyMMdd") + "') ";
                                            break;
                                        default:
                                            // String field
                                            strquery = strquery + " NOT (" + aField + " " + rDetail["OPERATOR"].ToString() + " '" + rDetail["VALUE"].ToString() + "') ";
                                            break;
                                    }
                                    break;
                            }
                        }
                        else if (rDetail[aCol].ToString().ToUpper() == "X")
                        {
                            errStr1 = errStr1 + rDetail["VALUE"].ToString() + ".";
                            if (rDetail["COMMAND"].ToString().ToUpper() == "ERROR")
                                isErr1 = 1;
                            //break;
                        }
                    }

                    if (strquery != "")
                    {
                        strquery = "  (" + strquery.Substring(7, strquery.Length - 7) + ")";
                    }
                    string aItem = "";
                    // de lam sau
                    DataRow[] arrdr = dttemp.Select(strquery);
                    if (arrdr.Length > 0)
                    {
                        for (int n = 0; n < arrdr.Length; n++)
                        {
                            X = true;
                            aItem = aItem + " " + arrdr[n]["ItemCode"].ToString();
                        }
                        if (X)
                        {
                            if (!string.IsNullOrEmpty(errStr1))
                                strErr = strErr + " \n " + ((aItem.Length) > 2 | true ? aItem.Substring(0, aItem.Length) + ": " : "") + errStr1;
                        }

                        result = isErr1;
                    }

                }
            }
            return result;
        }
    }
}
